package com.meida.dbr;

import com.yycx.groovy.provider.script.GroovyBinding;
import com.yycx.groovy.provider.script.MyGroovyScriptEngine;
import groovy.lang.GroovyShell;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * @Author: lly
 * @Date: 2023/7/1
 * <p>
 * 下面这段测试类包含两个，一个是有参数的调用，一个是无参数的调用
 * // 创建GroovyShell实例
 * // 创建Binding对象，用于传递参数和接收结果
 * // 设置参数
 * // 执行Groovy脚本
 * // 获取结果
 */
public class GroovyShellApp {
    private Log logger = LogFactory.getLog(MyGroovyScriptEngine.class);
    private GroovyBinding binding = new GroovyBinding();
    private GroovyShell shell = new GroovyShell(binding);

    public void execute(String script, Map<String, Object> vars) {
        executeObject(script, vars);
    }

    private void setParameters(GroovyShell shell, Map<String, Object> vars) {
        if (vars == null) {
            return;
        }
        Set<?> set = vars.entrySet();
        for (Iterator<?> it = set.iterator(); it.hasNext(); ) {
            @SuppressWarnings("rawtypes")
            Map.Entry entry = (Map.Entry) it.next();
            shell.setVariable((String) entry.getKey(), entry.getValue());
        }
    }

    public boolean executeBoolean(String script, Map<String, Object> vars) {
        Boolean rtn = (Boolean) executeObject(script, vars);
        return rtn.booleanValue();
    }

    public String executeString(String script, Map<String, Object> vars) {
        String str = (String) executeObject(script, vars);
        return str;
    }

    public int executeInt(String script, Map<String, Object> vars) {
        Integer rtn = (Integer) executeObject(script, vars);
        return rtn.intValue();
    }

    public float executeFloat(String script, Map<String, Object> vars) {
        Float rtn = (Float) executeObject(script, vars);
        return rtn.floatValue();
    }

    public Object executeObject(String script, Map<String, Object> vars) {
        this.logger.debug("执行:" + script);
        setParameters(shell, vars);
        script = script.replace("&apos;", "'").replace("&quot;", "\"").replace("&gt;", ">").replace("&lt;", "<").replace("&nuot;", "\n").replace("&amp;", "&");
        Object rtn = shell.evaluate(script);
        this.binding.clearVariables();
        return rtn;
    }


    /**
     * 根据公式计算
     */
    public BigDecimal executeBigDecimal(String formulaContent, Map<String, Object> dataSourceMap) {
        return executeBigDecimal(formulaContent, dataSourceMap, 3);
    }

    /**
     * 根据公式计算
     */
    public BigDecimal executeBigDecimal(String formulaContent, Map<String, Object> dataSourceMap, Integer scale) {
        BigDecimal amount = new BigDecimal("0.000");
        formulaContent = "return " + formulaContent;
        Object object = this.formulaParse(formulaContent, dataSourceMap);
        if (object instanceof Integer) {
            amount = new BigDecimal((int) object).setScale(scale, BigDecimal.ROUND_HALF_UP);
        }
        if (object instanceof Double) {
            amount = new BigDecimal((double) object).setScale(scale, BigDecimal.ROUND_HALF_UP);
        }
        if (object instanceof BigDecimal) {
            amount = ((BigDecimal) object).setScale(scale, BigDecimal.ROUND_HALF_UP);
        }
        return amount;
    }

    /**
     * 公式解析计算
     */
    public Object formulaParse(String formula, Map<String, Object> map) {
        Object value = this.executeObject(formula, map);
        return value;
    }


    public static void main(String[] args) {
        Map<String, Object> map = new HashMap<>();
        map.put("销售单价", 13.5);
        map.put("商务经理结算价", 11.8);
        map.put("最高加价", 1);
        map.put("数量", 2400);
        map.put("商务经理标准", 0.2);
        map.put("渠道商结算价", 13.5);
        map.put("渠道商标准", 0.2);
        map.put("已装修", true);

        // String content = "if(累计用量<2160){" + "if((累计用量+用量)>2160){" +
        // "未超出用量=(2160-累计用量);" + "超出用量=(用量-未超出用量);" +
        // "return 超出用量*0.61+未超出用量*0.56" + "}else{return 用量*0.56;" + "}" + "}" +
        // "else if(累计用量>=2160 && 累计用量<3120){" + "if((累计用量+用量)>3120){" +
        // "未超出用量=(3120-累计用量);" + "超出用量=(用量-未超出用量);" +
        // "return (超出用量*0.86)+(未超出用量*0.61)" + "}else{return 用量*0.61;" + "}" +
        // "}" + "else if(累计用量>3120){" + "return 用量*0.86;" + "}";
        // String cc =
        // "金额=((用量*单价)-3*高层户数+1.5*高层未入住户数)/(4*租赁户数+公摊总数-0.5*未入住户数);" +
        // "if(租赁){" + " return 金额*5;" + "};" + "if(高层&&已入住){" + "return 金额+3" +
        // "};" + "if(高层&&!已入住){" + "return 0.5*金额+1.5" + "};" + "if(已入住){" +
        // "return 金额;" + "};" + "if(!已入住){" + "return 金额*0.5;" + "};";
        String dd = "附加费=0;";

        dd += "if(楼层号>15){";

        dd += " 附加费=20;}";

        dd += "else{";

        dd += "附加费=15;";

        dd += "};";

        dd += "总附加费=抄表周期内装修户数* 附加费;";

        dd += "金额=((用量*单价-总附加费)-3*高层户数+2.5*高层未入住户数)/(4*租赁户数+已装修户数-0.5*未入住户数);";

        dd += "if(装修日期>=抄表开始日期&&装修日期<=抄表结束日期)";

        dd += "{";

        dd += "加收=附加费";

        dd += "}else";

        dd += "{";

        dd += "加收=0";

        dd += "};";

        dd += "if(!已装修)";

        dd += "{";

        dd += "return 0;";

        dd += "};";

        dd += "if(租赁)";

        dd += "{";

        dd += "return 金额*5+加收;";

        dd += "};";

        dd += "if(高层&&已入住)";

        dd += "{";

        dd += "return 金额+3+加收;";

        dd += "};";

        dd += "if(高层&&!已入住)";

        dd += "{";

        dd += "return 0.5*金额+1.5+加收;";

        dd += "};";

        dd += "if(已入住)";

        dd += "{";

        dd += " return 金额+加收;";

        dd += "};";

        dd += "if(!已入住)";

        dd += "{";

        dd += " return 金额*0.5+加收;";

        dd += "};";
        GroovyShellApp app = new GroovyShellApp();
        dd = "加价=0;";
        dd += "加价=(销售单价-商务经理结算价);";
        dd += "if(最高加价>0 && 加价>最高加价)";
        dd += "{";
        dd += "加价=3;";
        dd += "};";
        dd += "return 加价*数量*(1-商务经理标准)-(销售单价-渠道商结算价)*数量*(1-渠道商标准);";
        Object object = app.formulaParse(dd, map);

        System.out.print(object);
    }
}
